package main

import (
	"bytes"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"sync"

	requests "github.com/imroc/req"
)

type TSCache struct {
	content []byte
	size    int64
	lock    *sync.Cond
}

type TS struct {
	w          http.ResponseWriter
	r          *http.Request
	target     string
	targetSize int64
	cachesize  int
	startchan  chan int64
	buff       *bytes.Reader
}

func NewTSHandle(w http.ResponseWriter, r *http.Request, target string) *TS {
	return &TS{
		w:         w,
		r:         r,
		target:    target,
		cachesize: 1024 * 32,
		startchan: make(chan int64, 1),
	}

}
func (server *TS) Handle() {
	// fmt.Println("blcok", server.target)
	var contentlength int64
	if _, ok := lrucache.Get(server.target); ok == false {
		go func() {
			if server.targetSize > 0 {
				server.startchan <- server.targetSize
			} else {
				server.GetNewChunk()
			}
		}()
		contentlength, _ = <-server.startchan
		fmt.Println("开始发送头给终端", contentlength)
	} else {
		if _obj, ok := lrucache.Get(server.target); ok == true {
			contentlength = _obj.(*TSCache).size
		}
	}
	server.w.Header().Set("Connection", "close")
	server.w.Header().Set("Cache-Control", "public, max-age=0")
	server.w.Header().Set("Content-Length", strconv.FormatInt(contentlength, 10))
	server.w.Header().Set("Content-Type", "video/MP2T")
	server.w.WriteHeader(200)
	if _obj, ok := lrucache.Get(server.target); ok == true {
		cacheObj := _obj.(*TSCache)
		buf := make([]byte, server.cachesize)
		var last int64 = 0
		lock := cacheObj.lock
		for {
			_cache := cacheObj.content
			if int64(len(_cache)) <= last {
				lock.L.Lock()
				lock.Wait()
				lock.L.Unlock()
			}
			n := copy(buf, _cache[last:])
			last += int64(n)
			server.w.Write(buf[:n])
			if last >= contentlength {
				break
			}
		}
	}
}
func (server *TS) GetNewChunk() {
	var cacheObj *TSCache
	if _, ok := lrucache.Get(server.target); ok == false {
		m := sync.Mutex{}
		cacheObj = &TSCache{
			lock: sync.NewCond(&m),
		}
		lrucache.Add(server.target, cacheObj)
		fmt.Println(lrucache.Len())
	}

	fmt.Printf(DebugColor, server.target)
	_r, err := requests.Get(server.target)
	server.PanicError(err)
	resp := _r.Response()
	defer func() {
		resp.Body.Close()
	}()
	contentLength, err := strconv.Atoi(resp.Header.Get("Content-Length"))
	server.PanicError(err)
	// fmt.Println(contentLength)
	if resp.StatusCode == 200 {
		cacheObj.content = make([]byte, 0, contentLength)
		server.targetSize = int64(contentLength)
		cacheObj.size = int64(contentLength)
		server.startchan <- server.targetSize
		buff := make([]byte, server.cachesize)
		total := 0
		i := 0

		for {
			length, err := io.ReadAtLeast(resp.Body, buff, server.cachesize)
			if length > 0 {
				total += length
				// fmt.Printf("%p 1 \n", cacheObj.content)
				cacheObj.content = append(cacheObj.content, buff[:length]...)
				// fmt.Printf("%p 2 \n", cacheObj.content)

				// lrucache.Put(server.target, _new)
				// _this := lrucache.Get(server.target).([]byte)
				// fmt.Printf("%d %d %p %p %p \n", len(_this), len(_cache), _this, _cache, _new)
				// fmt.Println(buff[:10], _cache[:10])
				// fmt.Printf(DebugColor, "GetNewChunk"+server.r.URL.RawQuery)
				cacheObj.lock.Broadcast()
				// server.downloadchan <- 1
			}
			if err != nil {
				// server.PrintError(err)
				break
			}
			i++
		}
		// close(server.downloadchan)
	}
}
func (this *TS) PanicError(err error) {
	if err != nil {
		panic(err)
	}
}
func (this *TS) PrintError(err error) {
	if err != nil {
		fmt.Println(err)
	}
}
